
#ifndef PF2DOT_H
#define PF2DOT_H

/**
This file declare the class of pf2dot.
The pf2dot class is used to convert a power flow struct to a dot file, which can be further used to visualize the power flow.
One can use the "dot" tool available from http://www.graphviz.org to convert the dot file to many kinds of graph output, including gif, png, svg, and Postscript. 

$Id$

*/

#include <complex>
#include <iostream>
#include <map>
#include <string>
#include <vector>

namespace nm_pslab{

/**
 This class declare the property-value map, based on std::map<string, std::string>.
 A function is provided to generate the std::string.
*/
class PropVal : public std::map<std::string, std::string>{
public:
   PropVal();
   /**
    Generate the string as "prop = val, prop = val, ...".
   */
   std::string GenStr()const;
};



/**
 This class declare the element corresponding to the dot format.
 Todo: maybe is possible to find this class the in the dot implementation.
*/
class Dot{
public:
   Dot(); /// Default constructor.
   //Todo Properly use inline.
   Dot(bool _dir); ///Constructor that initialize dir;
   Dot& SetName(const std::string& _name); ///constructor that initialize name;

   /**
    To insert an edge.
   */
   struct Edge;
   Edge& InsertEdge(const std::string& _nd1_name, const std::string& _nd2_name, const std::string& _e_name);
   
   /**
    To insert a node.
   */
   struct Node;
   Node& InsertNode(const std::string& _name);
   	
   /**
    Is dir?
   */
   inline bool IsDir()const;
   
   /**
    Get name
   */
   inline const std::string& GetName()const;
   
   /**
    Output all the items.
   */
   std::ostream& OutputItems(std::ostream& _os_)const;

//   friend std::ostream& operator << (std::ostream& _os_, const Dot& _dot);

   /**
    Declare the Node in dot format. 
   */
   struct Node{
   	  /**
   	  Default constructor.
   	  */
      Node();
      /**
      Constructor that initialize the node name.
      */
      Node(const std::string& _name);
      	
      std::string m_name;
   };

   /**
    Declare the Edge in dot format.
   */
   struct Edge{
      /**
       Default constructor.
      */
      Edge();
      
      /**
         Constructor that innitializes the edge name and node names.
      */
      Edge(const std::string& _nd1_name, const std::string& _nd2_name, const std::string& _name);
      std::string m_name;
      //Todo: properly use "using namespace std"
      std::string m_nd1_name;
      std::string m_nd2_name;
      PropVal m_prop_val;
   };
protected:
   std::string m_name;
   bool m_dir;
   std::vector<Node> m_node_vec;
   std::vector<Edge> m_edge_vec;
};

/**
 To output the dot stream.
*/
std::ostream& operator << (std::ostream& _os_, const Dot& _dot);

/**
 To output a Dot::Node stream.
*/
std::ostream& operator << (std::ostream& _os_, const Dot::Node& _dot_node);

/**
 To output a Dot::Edge stream.
*/
std::ostream& operator << (std::ostream& _os_, const Dot::Edge& _dot_edge);
	
/**
 This class declare the power flow information that will be used to generate dot file.
 A corresponding funciton is provided to generate the dot file.
*/

class Pf4Dot{
public:
   /**
    Default constructor.
   */
   Pf4Dot();
   /**
    Constructor that initialize the name.
   */
   Pf4Dot(const std::string& _name);
   /**
    To insert a line.
   */
   struct Ln;
   Ln& InsertLn(const std::string& _name, const std::string& _ist_name, const std::string& _zst_name,
     double _ip, double _iq, double _zp, double _zq, int island);
   /**
    To generate the dot stream.
   */
   void GenDot(std::ostream& _os_);
   /**
    Declare a Line information for generating dot.
   */
   struct Ln{
      /**
       Constructor that initialize the line name, st names and p/q powers of both ends.
      */
      Ln(const std::string& _name, const std::string& _ist_name, const std::string& _zst_name,
        double _ip, double _iq, double _zp, double _zq, int _island);
      /**
       To generate a std::string a the lable of the edge in dot file.
      */
      std::string GenEdgeLabel()const;
      Ln& SetIsland();
      std::string m_name;
      std::string m_ist_name;
      std::string m_zst_name;
      int  m_island;
      std::complex<double> m_ipower;
      std::complex<double> m_zpower;
   };
protected:
   std::string m_name;
   std::vector<Ln> m_ln_vec;
};

};

#endif
